/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.appspot.ittrick.drive.trick.controller;

import com.appspot.ittrick.drive.trick.Constants;
import com.appspot.ittrick.drive.trick.DriveTrick;
import com.appspot.ittrick.drive.trick.api.GoogleOauthAPIService;
import com.appspot.ittrick.drive.trick.api.exception.CodeExchangeException;
import com.appspot.ittrick.drive.trick.db.AccountMstEntity;
import com.appspot.ittrick.drive.trick.db.DBManager;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.oauth2.Oauth2;
import com.google.api.services.oauth2.model.Userinfo;
import java.io.IOException;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.URL;
import java.sql.SQLException;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Cursor;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;

/**
 *
 * @author takahara
 */
public class MenuController extends BorderPane implements Initializable {
    
    @FXML
    private FlowPane accontFlowPane;
    
    /**
     * コンストラクタ
     */
    public MenuController() {
        loadFXML();
    }
    
    /**
     * 初期化メソッド
     */
    private void loadFXML() {
        // ---------------------------------------------------
        // FXMLのロードと設定
        // ---------------------------------------------------
        FXMLLoader fxmlLoader = new FXMLLoader(DriveTrick.class.getResource("fxml/menu.fxml"));
        fxmlLoader.setRoot(this);
        // 自分自身をコントロールとして設定
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        try {
            initAccontFlowPane();
        } catch (SQLException ex) {
            Logger.getLogger(MenuController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
    private void initAccontFlowPane() throws SQLException {
        List<AccountMstEntity> acconutEntityList = DBManager.getAccountList(DBManager.getConn());
        
        // 戻り値のimageViewListの初期化
        ObservableList<Label> imageViewList = FXCollections.observableArrayList();
        
        for(AccountMstEntity entity: acconutEntityList) {
            imageViewList.add(getMenuLabelView(entity));
        }
        
        accontFlowPane.getChildren().setAll(imageViewList);
    }
    
    private Label getMenuLabelView(final AccountMstEntity accountMstEntity) {

        // -----------------------------------------
        // 画像の設定
        // -----------------------------------------
//        ImageView imageView;
//        if (accountMstEntity.pictureUrl != null) {
//            imageView = new ImageView(accountMstEntity.pictureUrl);
//        } else {
//            imageView = new ImageView(DriveTrick.class.getResource("images/gdrive.png").toString());
//        }
        
        ImageView imageView = new ImageView(DriveTrick.class.getResource("images/gdrive.png").toString());
        imageView.setFitWidth(120);
        imageView.setPreserveRatio(true);
        // 影の設定
        DropShadow ds1 = new DropShadow();
        ds1.setOffsetY(4.0f);
        ds1.setOffsetX(4.0f);
        ds1.setColor(Color.color(0.4f, 0.4f, 0.4f));
        imageView.setEffect(ds1);

        // -----------------------------------------
        // imageラベルの設定
        // -----------------------------------------
        Label imageLabel = LabelBuilder.create().graphic(imageView).build();
        imageLabel.setCursor(Cursor.HAND);
        imageLabel.setText(accountMstEntity.name);
        imageLabel.setContentDisplay(ContentDisplay.TOP);
        
        // -----------------------------------------
        // クリックイベントの設定
        // -----------------------------------------
        imageLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {

                // マウスの左ボタンがクリックされた場合
                if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {

                    DriveTrick.getInstance().sendMainController(accountMstEntity.mailAddress);
                }
            }
        });
        
        return imageLabel;
    }
    
    @FXML
    protected void addAccontAction() throws IOException {
        OAuthController controller = new OAuthController();
        
        // authorizationUrl取得
        String authorizationUrl = GoogleOauthAPIService.getAuthorizationUrl();
        
        // 承認処理
        controller.oauthWebView.getEngine().locationProperty().addListener(new ChangeListener<String>() {

            @Override
            public void changed(ObservableValue<? extends String> ov, String before, String after) {
                if (after.startsWith(GoogleOauthAPIService.REDIRECT_URI)) {
                    String[] tmp = after.split("code=");
                    String authorizationCode = tmp[1];
                    
                    if (authorizationCode != null) {
                        System.out.println("Authorization Code: " + authorizationCode);
                        
                        try {
                            // Googleから承認情報を取得
                            Credential credential = GoogleOauthAPIService.exchangeCode(authorizationCode);

                            // ユーザー情報の取得
                            Userinfo userinfo = getUserInfo(credential);
                            
                            // 承認情報をDBに保存
                            DBManager.insertOrUpdateAccontMst(
                                    DBManager.getConn(),
                                    userinfo.getEmail(),
                                    userinfo.getName(), 
                                    userinfo.getId(), 
                                    userinfo.getPicture(), 
                                    credential.getAccessToken(),
                                    credential.getRefreshToken());
                            
                            // 表示アカウント更新
                            initAccontFlowPane();
                            
                            // 承認画面を閉じる
                            DriveTrick.getInstance().closeOAuthStage();
                            

                        } catch (CodeExchangeException | SQLException | IOException ex) {
                            DriveTrick.getInstance().displayErrorPop(ex);
                            Logger.getLogger(MainController.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
            }
            
        });
        
        // 新しいCookieManagerを生成し、WebViewのCookieをクリアーする
        final CookieManager manager = new CookieManager();
        manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        CookieHandler.setDefault(manager);
        
        // 承認画面の表示
        DriveTrick.getInstance().showOAuthStage(controller);
        controller.oauthWebView.getEngine().load(authorizationUrl);
    }
    
    /**
     * ユーザー情報の取得
     *
     * @param credentials
     * @return
     */
    private Userinfo getUserInfo(Credential credentials) throws IOException {
        Oauth2 userInfoService =
                new Oauth2.Builder(new NetHttpTransport(), new JacksonFactory(), credentials)
                .setApplicationName(Constants.APPLICATION_NAME)
                .build();
        Userinfo userInfo = userInfoService.userinfo().get().execute();

        return userInfo;
    }

}
